home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nothing but Tetris
/
Nothing but Tetris.iso
/
menu.lha
/
IBMPC
/
MIXED2
/
C_TETRIS
/
T_TRIS.C
next >
Wrap
Text File
|
1980-01-06
|
30KB
|
995 lines
/* T_TRIS version 2.01 adapted by Eric Lapaille
Quai du Condroz 17
B - 4020 LIEGE
BELGIUM
English translation.
Modified for Turbo C 2.0.
Cursor and mouse hiding.
Please, leave this header unmodified
I don't know if the original TETRIS is a commercial product, a public
domain or anyone else. So, if this T_TRIS violates any copyright law
or causes prejudice to some people, please let me know and I'll
immediately remove T_TRIS from the PD market.
If you like this product and use it often, respect the shareware concept
and send to one of us a disk full of great public domain software.
Sorry for spelling errors, but my native tongue is FRENCH. */
/* ---------------------------------------------------------------------- */
/* T_TRIS */
/* Taak Leuk spelen met de gebruiker */
/* */
/* Compiler MicroSoft C 5.0 Large Model */
/* Quick C 1.0 ,, ,, */
/* */
/* (c) 1988 R.A. van Wier */
/* Nwe Prinsengr. 60 II */
/* 1018 VT Amsterdam */
/* */
/* Dit programma is een "kloon" van het tetris programma */
/* van A. Pajitnov & V. Gerasimov. */
/* */
/* Deze software mag door iedereen gebruikt, gecopieerd, */
/* aangepast en verspreid worden onder voorwaarde dat altijd */
/* de juiste source wordt meegeleverd en dat de CopyRight */
/* teksten niet worden verwijderd. */
/* */
/* Houdt FreeWare VIRUS vrij, lever de SOURCE mee ! */
/* */
/* ---------------------------------------------------------------------- */
#include <bios.h>
#include <conio.h>
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
static int REACTION_TIME,
start_level,
level;
static char name[255];
#define MDA_SEG 0xB000
#define CGA_SEG 0xB800
#define KEY_END 0x011B
#define KEY_RIGHT 0x4D00
#define KEY_LEFT 0x4B00
#define KEY_PAUSE 0x4800
#define KEY_DROP 0x5000
#define KEY_ROTATE 0x1C0D
#define MOUSE_STEP 16
#define SCREEN_BLANKING 0x0700 | ' '
#define CHAR_FULL (unsigned char)219
#define COLOR_BLACK 0
#define COLOR_BROWN 6
#define COLOR_GREY 7
#define COLOR_GREEN 10
#define COLOR_BLUE 11
#define COLOR_RED 12
#define COLOR_VIOLET 13
#define COLOR_YELLOW 14
#define COLOR_WHITE 15
#define COLOR_SCORE 75
#define COLOR_TOPSCORE 30
#define COLOR_LOGO 31
#define COLOR_RAND 3
#define LOG_SIZE_REG 20
#define LOG_SIZE_COL 10
#define MIN_REG 2
#define MAX_REG (LOG_SIZE_REG + MIN_REG)
#define MIN_COL 28
#define MAX_COL (MIN_COL + (LOG_SIZE_COL * 2))
#define NUMBER_FORMS 7
#define FORM_SIZE 3
#define SCORE_FILE "T_TRIS.TOP"
#define NUMBER_SCORE 20
typedef int FORM[FORM_SIZE][FORM_SIZE];
static FORM forms[NUMBER_FORMS];
static FORM huidige_form;
static int form_point[NUMBER_FORMS];
static int log_screen[LOG_SIZE_REG][LOG_SIZE_COL];
static unsigned far *ptr_screen;
static int col;
static long points;
static unsigned key;
static int mouse_present = -1, mouse_col;
/* ----------- position the cursor ------------- */
void cursor(int x, int y)
{
union REGS rg;
rg.x.ax = 0x0200;
rg.x.bx = 0;
rg.x.dx = ((y << 8) & 0xff00) + x;
int86(16, &rg, &rg);
}
/* ---------------------------------------------------------------------- */
/* CHECK_MOUSE */
/* Test if mouse is present */
/* */
/* ---------------------------------------------------------------------- */
static void check_mouse()
{
union REGS regs;
regs.x.ax = 0;
int86(0x33,®s,®s);
if ( regs.x.ax == 0 )
mouse_present = 0;
else
mouse_present = 1;
if ( mouse_present )
{
regs.x.ax = 3;
int86(0x33,®s,®s);
mouse_col = regs.x.cx;
regs.x.ax = 7;
regs.x.cx = MIN_COL * 8;
regs.x.dx = (MAX_COL-1) * 8;
int86(0x33,®s,®s);
}
}
/* ---------------------------------------------------------------------- */
/* MOUSE_CLICK */
/* Check for mouse click */
/* */
/* ---------------------------------------------------------------------- */
static int mouse_click()
{
int retcode;
union REGS regs;
static unsigned vclick = 0;
regs.x.ax = 3;
int86(0x33,®s,®s);
if ( ( regs.x.bx != 0 ) && ( regs.x.bx != vclick ) )
retcode = 1;
else
retcode = 0;
vclick = regs.x.bx;
return(retcode);
}
/* ---------------------------------------------------------------------- */
/* READ_MOUSE */
/* Read mouse move */
/* */
/* ---------------------------------------------------------------------- */
static int read_mouse()
{
int retcode;
union REGS regs;
retcode = 0;
if ( mouse_present < 0 )
check_mouse();
if ( mouse_present )
{
if ( mouse_click() )
{
key = KEY_ROTATE;
retcode = 1;
}
else
{
regs.x.ax = 3;
int86(0x33,®s,®s);
if ( (mouse_col - (int)regs.x.cx) >= MOUSE_STEP )
{
key = KEY_LEFT;
mouse_col -= MOUSE_STEP;
retcode = 1;
}
else
{
if ( ( (int)regs.x.cx - mouse_col) >= MOUSE_STEP )
{
key = KEY_RIGHT;
mouse_col += MOUSE_STEP;
retcode = 1;
}
else
{
regs.x.ax = 11;
int86(0x33,®s,®s);
if ( (int)regs.x.dx >= MOUSE_STEP )
{
key = KEY_DROP;
retcode = 1;
}
}
}
}
}
return(retcode);
}
/* ---------------------------------------------------------------------- */
/* ACTION */
/* Check for reaction time */
/* */
/* ---------------------------------------------------------------------- */
static int action()
{
int retcode;
static long last = 0,
delay;
#if Microsoft
_bios_timeofday(_TIME_GETCLOCK,&delay);
#else
delay=biostime(0,delay);
#endif
if ( ( delay - last ) >= REACTION_TIME )
{
retcode = 1;
last = delay;
}
else
retcode = 0;
return(retcode);
}
/* ---------------------------------------------------------------------- */
/* READ_KEY */
/* Check and read key hitting */
/* */
/* ---------------------------------------------------------------------- */
static int read_key()
{
int retcode;
if ( bioskey(1) )
{
key = bioskey(0);
retcode = 1;
}
else
retcode = read_mouse();
return(retcode);
}
static void wait_key()
{
while( ( !read_key() ) && ( !read_mouse() ) );
}
static void flush_key_buffer()
{
while ( ( read_key() ) || ( read_mouse() ) );
}
/* ---------------------------------------------------------------------- */
/* BEEP */
/* Performs beep */
/* */
/* ---------------------------------------------------------------------- */
static void beep()
{
putch('\x07');
}
/* ---------------------------------------------------------------------- */
/* SHOW_DRAWING */
/* Show the right form in the right color */
/* */
/* ---------------------------------------------------------------------- */
static void show_drawing(line,column,color,drawing)
int line,
column,
color;
unsigned
char drawing;
{
int i;
i = (line * 80) + column;
ptr_screen[i] = (color << 8) | drawing;
}
/* ---------------------------------------------------------------------- */
/* SHOW_STRING */
/* Show the right string at the right place in the right color */
/* */
/* ---------------------------------------------------------------------- */
static void show_string(line,column,color,string)
int line,
column,
color;
unsigned
char string[];
{
int i;
for ( i = 0; string[i]; i++ )
show_drawing(line,column+i,color,string[i]);
}
/* ---------------------------------------------------------------------- */
/* CLS */
/* */
/* ---------------------------------------------------------------------- */
static void cls()
{
int i;
for ( i = 0; i < 2000; i++) ptr_screen[i] = SCREEN_BLANKING;
}
/* ---------------------------------------------------------------------- */
/* INIT_SCREEN */
/* Layout of the screen */
/* */
/* ---------------------------------------------------------------------- */
static void init_screen()
{
int i;
union REGS regs;
char mystring[100];
long delay;
/* Timer and screen initialization */
regs.h.ah = 0x0F;
int86(0x10,®s,®s);
#if Microsoft
_bios_timeofday(_TIME_GETCLOCK,&delay);
#else
delay=biostime(0,delay);
#endif
srand(delay % 32113);
if ( regs.h.al == 7 )
{
#if Microsoft
FP_SEG(ptr_screen) = MDA_SEG;
FP_OFF(ptr_screen) = 0x0000;
#else
ptr_screen = MK_FP(MDA_SEG,0);
#endif
}
else
{
#if Microsoft
FP_SEG(ptr_screen) = CGA_SEG;
FP_OFF(ptr_screen) = 0x0000;
#else
ptr_screen = MK_FP(CGA_SEG,0);
#endif
}
cls();
for ( i = MIN_REG ; i <= MAX_REG; i++ )
{
show_drawing(i,MIN_COL-1,COLOR_RAND,CHAR_FULL);
show_drawing(i,MAX_COL,COLOR_RAND,CHAR_FULL);
}
for ( i = (MIN_COL -1) ; i <= MAX_COL; i++ )
show_drawing(MAX_REG,i,COLOR_RAND,CHAR_FULL);
sprintf(mystring, " T _ T R I S 2.01m %-20.20s (c) 1989, RvW - EL ",name);
show_string(0, 0,COLOR_LOGO,mystring);
check_mouse();
if ( mouse_present )
show_string(24,0,COLOR_LOGO," Mouse/Key : LEFT, DOWN, RIGHT, UP=pause CLICK/RETURN=rotate ESC=end ");
else
show_string(24,0,COLOR_LOGO," Key : cursor LEFT, DOWN, RIGHT UP=pause RETURN=rotate ESC=end ");
}
/* ---------------------------------------------------------------------- */
/* SHOW_SCORE */
/* Show score and level */
/* */
/* ---------------------------------------------------------------------- */
static void show_score()
{
char mystring[80];
show_string(10,0,COLOR_SCORE," ");
sprintf(mystring," Level %1d / %1d ",start_level,level);
show_string(11,0,COLOR_SCORE,mystring);
show_string(12,0,COLOR_SCORE," ");
sprintf(mystring," Score %5ld ",points);
show_string(13,0,COLOR_SCORE,mystring);
show_string(14,0,COLOR_SCORE," ");
}
/* ---------------------------------------------------------------------- */
/* SHOW_TOPSCORE */
/* Show one topscore by player */
/* */
/* ---------------------------------------------------------------------- */
static void show_topscore()
{
int i,
j;
char mystring[80];
long mystring_score,
mystring_gem,
mystring_gesp;
static struct
{
int number;
long score[NUMBER_SCORE];
long gem[NUMBER_SCORE];
long gesp[NUMBER_SCORE];
char name[NUMBER_SCORE][22];
} score_record;
FILE *score_filename;
/* Read old scores */
score_filename = fopen(SCORE_FILE,"rb");
if ( score_filename == NULL )
score_record.number = 0;
else
{
if ( fread(&score_record,sizeof(score_record),1,score_filename) < 1)
score_record.number = 0;
fclose(score_filename);
}
/* Look for player in the list */
name[21] = '\0';
strupr(name);
j = 99;
for ( i = 0; i < score_record.number; i++ )
{
if ( strcmp(name,score_record.name[i]) == 0 )
j = i;
}
if ( j < 99 )
{
/* Compute score and average */
if ( points > score_record.score[j] )
score_record.score[j] = points;
score_record.gem[j] = ( ( score_record.gem[j] * score_record.gesp[j] )
+ points ) / ( score_record.gesp[j] + 1);
score_record.gesp[j] = score_record.gesp[j] + 1;
}
else
{
if ( score_record.number < NUMBER_SCORE )
{
score_record.score[score_record.number] = points;
score_record.gem[score_record.number] = points;
score_record.gesp[score_record.number] = 1;
strcpy(score_record.name[score_record.number],name);
j = score_record.number;
score_record.number++;
}
else
{
if ( points > score_record.score[NUMBER_SCORE - 1] )
{
/* Remove last score and replace it my new score */
score_record.score[NUMBER_SCORE - 1] = points;
score_record.gem[NUMBER_SCORE - 1] = points;
score_record.gesp[NUMBER_SCORE - 1] = 1;
strcpy(score_record.name[NUMBER_SCORE - 1],name);
j = NUMBER_SCORE - 1;
}
}
}
if ( j < 99 )
{
while ( ( j > 0 ) && ( score_record.score[j] > score_record.score[j-1] ) )
{
strcpy(mystring,score_record.name[j-1]);
mystring_score = score_record.score[j-1];
mystring_gem = score_record.gem[j-1];
mystring_gesp = score_record.gesp[j-1];
strcpy(score_record.name[j-1],score_record.name[j]);
score_record.score[j-1] = score_record.score[j];
score_record.gem[j-1] = score_record.gem[j];
score_record.gesp[j-1] = score_record.gesp[j];
strcpy(score_record.name[j],mystring);
score_record.score[j] = mystring_score;
score_record.gem[j] = mystring_gem;
score_record.gesp[j] = mystring_gesp;
j--;
}
}
score_filename = fopen(SCORE_FILE,"wb");
if ( score_filename != NULL )
{
fwrite(&score_record,sizeof(score_record),1,score_filename);
fclose(score_filename);
}
/* Show score list on the screen */
for (i = 0; i < LOG_SIZE_REG; i++)
{
if ( i < score_record.number )
sprintf(mystring," Top %5ld, Avg. %5ld pnt. for %-16.16s ",
score_record.score[i],
score_record.gem[i],score_record.name[i]);
else
strcpy(mystring," ");
show_string(MIN_REG+i,MIN_COL,COLOR_TOPSCORE,mystring);
}
}
/* ---------------------------------------------------------------------- */
/* LOG_DISPLAY */
/* */
/* ---------------------------------------------------------------------- */
static void log_display()
{
int i,j;
for ( i = 0; i < LOG_SIZE_REG; i++ )
{
for ( j = 0; j < LOG_SIZE_COL; j++ )
{
show_drawing(MIN_REG+i,MIN_COL+(j*2),log_screen[i][j],CHAR_FULL);
show_drawing(MIN_REG+i,MIN_COL+1+(j*2),log_screen[i][j],CHAR_FULL);
}
}
}
/* ---------------------------------------------------------------------- */
/* LOG_CLS */
/* */
/* ---------------------------------------------------------------------- */
static void log_cls()
{
int i,j;
for ( i = 0 ; i < LOG_SIZE_REG; i++)
{
for ( j = 0; j < LOG_SIZE_COL; j++)
log_screen[i][j] = COLOR_BLACK;
}
log_display();
check_mouse();
}
static void remove_full_line()
{
int i,
j;
int x,
action;
for ( i = LOG_SIZE_REG - 1 ; i > 0; i--)
{
/* Look for a gap on the line */
action = 1;
for ( j = 0; j < LOG_SIZE_COL; j++)
{
if (log_screen[i][j] == COLOR_BLACK)
action = 0;
}
if ( action )
{
for ( x = i ; x > 0; x--)
{
for ( j = 0; j < LOG_SIZE_COL; j++)
log_screen[x][j] = log_screen[x-1][j];
}
for ( j = 0; j < LOG_SIZE_COL; j++)
log_screen[0][j] = COLOR_BLACK;
beep();
i++;
}
}
log_display();
}
/* ---------------------------------------------------------------------- */
/* SHOW_FORM */
/* Form manipulation */
/* ---------------------------------------------------------------------- */
static int show_form(action)
int action; /* 0 = init */
/* 1 = down */
/* 2 = right */
/* 3 = left */
/* 5 = rotate */
{
int i,j;
static int reg,col;
int mystring,change;
change = 1;
if ( action != 0 )
{
/* Blank old position */
for ( i = 0; i < 3; i++ )
{
for ( j = 0; j < 3; j++ )
{
if ( huidige_form[i][j] != COLOR_BLACK )
log_screen[reg+i][col+j] = COLOR_BLACK;
}
}
}
switch(action)
{
case 0 :
reg = 0;
col = LOG_SIZE_COL / 2;
check_mouse();
break;
case 1 :
reg++;
break;
case 2 :
col++;
break;
case 3 :
col--;
break;
case 5 :
mystring = huidige_form[0][0];
huidige_form[0][0] = huidige_form[2][0];
huidige_form[2][0] = huidige_form[2][2];
huidige_form[2][2] = huidige_form[0][2];
huidige_form[0][2] = mystring;
mystring = huidige_form[0][1];
huidige_form[0][1] = huidige_form[1][0];
huidige_form[1][0] = huidige_form[2][1];
huidige_form[2][1] = huidige_form[1][2];
huidige_form[1][2] = mystring;
break;
}
for ( i = 0; i < 3; i++ )
{
for ( j = 0; j < 3; j++ )
{
if ( huidige_form[i][j] != COLOR_BLACK )
{
if ( log_screen[reg+i][col+j] != COLOR_BLACK )
change = 0;
if ( ( reg+i ) >= LOG_SIZE_REG )
change = 0;
if ( ( reg+i ) < 0 )
change = 0;
if ( ( col+j ) >= LOG_SIZE_COL )
change = 0;
if ( ( col+j ) < 0 )
change = 0;
}
}
}
if ( !change )
{
switch(action)
{
case 1 :
reg--;
break;
case 2 :
col--;
break;
case 3 :
col++;
break;
case 5 :
mystring = huidige_form[0][0];
huidige_form[0][0] = huidige_form[0][2];
huidige_form[0][2] = huidige_form[2][2];
huidige_form[2][2] = huidige_form[2][0];
huidige_form[2][0] = mystring;
mystring = huidige_form[0][1];
huidige_form[0][1] = huidige_form[1][2];
huidige_form[1][2] = huidige_form[2][1];
huidige_form[2][1] = huidige_form[1][0];
huidige_form[1][0] = mystring;
break;
}
}
/* form at new position */
for ( i = 0; i < 3; i++ )
{
for ( j = 0; j < 3; j++ )
{
if ( huidige_form[i][j] != COLOR_BLACK )
log_screen[reg+i][col+j] = huidige_form[i][j];
}
}
log_display();
return(change);
}
/* ---------------------------------------------------------------------- */
/* INIT_FORMS */
/* */
/* ---------------------------------------------------------------------- */
static void init_forms()
{
int i,
j;
int color;
form_point[0] = 10;
color = COLOR_BROWN;
forms[0][0][0] = COLOR_BLACK; /* ..# */
forms[0][0][1] = COLOR_BLACK; /* .## */
forms[0][0][2] = color; /* .#. */
forms[0][1][0] = COLOR_BLACK;
forms[0][1][1] = color;
forms[0][1][2] = color;
forms[0][2][0] = COLOR_BLACK;
forms[0][2][1] = color;
forms[0][2][2] = COLOR_BLACK;
form_point[1] = 10;
color = COLOR_BLUE;
forms[1][0][0] = color ; /* #.. */
forms[1][0][1] = COLOR_BLACK; /* ##. */
forms[1][0][2] = COLOR_BLACK; /* .#. */
forms[1][1][0] = color ;
forms[1][1][1] = color ;
forms[1][1][2] = COLOR_BLACK;
forms[1][2][0] = COLOR_BLACK;
forms[1][2][1] = color ;
forms[1][2][2] = COLOR_BLACK;
form_point[2] = 1;
color = COLOR_RED;
forms[2][0][0] = COLOR_BLACK; /* ... */
forms[2][0][1] = COLOR_BLACK; /* ### */
forms[2][0][2] = COLOR_BLACK; /* ... */
forms[2][1][0] = color ;
forms[2][1][1] = color ;
forms[2][1][2] = color ;
forms[2][2][0] = COLOR_BLACK;
forms[2][2][1] = COLOR_BLACK;
forms[2][2][2] = COLOR_BLACK;
form_point[3] = 7;
color = COLOR_VIOLET;
forms[3][0][0] = COLOR_BLACK; /* ... */
forms[3][0][1] = COLOR_BLACK; /* ### */
forms[3][0][2] = COLOR_BLACK; /* ..# */
forms[3][1][0] = color ;
forms[3][1][1] = color ;
forms[3][1][2] = color ;
forms[3][2][0] = COLOR_BLACK;
forms[3][2][1] = COLOR_BLACK;
forms[3][2][2] = color ;
form_point[4] = 7;
color = COLOR_YELLOW;
forms[4][0][0] = COLOR_BLACK; /* ... */
forms[4][0][1] = COLOR_BLACK; /* ### */
forms[4][0][2] = COLOR_BLACK; /* #.. */
forms[4][1][0] = color ;
forms[4][1][1] = color ;
forms[4][1][2] = color ;
forms[4][2][0] = color ;
forms[4][2][1] = COLOR_BLACK;
forms[4][2][2] = COLOR_BLACK;
form_point[5] = 4;
color = COLOR_GREY;
forms[5][0][0] = COLOR_BLACK; /* ... */
forms[5][0][1] = COLOR_BLACK; /* ##. */
forms[5][0][2] = COLOR_BLACK; /* ##. */
forms[5][1][0] = color ;
forms[5][1][1] = color ;
forms[5][1][2] = COLOR_BLACK;
forms[5][2][0] = color ;
forms[5][2][1] = color ;
forms[5][2][2] = COLOR_BLACK;
form_point[6] = 3;
color = COLOR_GREEN;
forms[6][0][0] = COLOR_BLACK; /* ... */
forms[6][0][1] = COLOR_BLACK; /* .#. */
forms[6][0][2] = COLOR_BLACK; /* ### */
forms[6][1][0] = COLOR_BLACK;
forms[6][1][1] = color ;
forms[6][1][2] = COLOR_BLACK;
forms[6][2][0] = color ;
forms[6][2][1] = color ;
forms[6][2][2] = color;
}
/* ---------------------------------------------------------------------- */
/* CHOOSE_FORM */
/* Random choose of the form */
/* */
/* ---------------------------------------------------------------------- */
static void choose_form()
{
int i,j,x;
static int tel = 0;
static long vpunten = 0;
if ( vpunten > points )
{
vpunten = 0;
tel = 0;
}
x = rand() % NUMBER_FORMS;
for ( i = 0; i < 3 ; i++)
{
for ( j = 0; j < 3; j++ )
huidige_form[i][j] = forms[x][i][j];
}
points += form_point[x] + start_level;
tel++;
if ( ( ( tel % 25 ) == 0 ) && ( level < 9 ) )
{
level++;
beep();
}
show_score();
vpunten = points;
REACTION_TIME = 10 - level;
}
/* ------------------------------------------------------------------------ */
/* */
/* MAIN */
/* */
/* ------------------------------------------------------------------------ */
void main()
{
int i;
char strlevel[3];
key = 0;
while ( key != KEY_END )
{
level = 99;
strcpy(name,"");
while ( name[0] == '\0' )
{
clrscr();
printf("\nWhat is your name > ");
gets(name);
}
while ( ( level < 0 ) || ( level > 9 ) )
{
printf("\nDear %s, choose your level ( 0..9) > ",name);
gets(strlevel);
level=atoi(strlevel);
}
cursor(0,26);
start_level = level;
points = 0;
init_screen();
log_cls();
init_forms();
choose_form();
key = 0;
while ( ( key != KEY_END ) && ( show_form(0) ) )
{
while ( ( key != KEY_END ) && ( show_form(1) ) )
{
action();
while ( ( !action() ) && ( key != KEY_END ) )
{
if ( read_key() )
{
switch(key)
{
case KEY_RIGHT :
show_form(2);
break;
case KEY_LEFT :
show_form(3);
break;
case KEY_DROP :
i = 0;
while( show_form(1)) i++;
points = points + start_level +
((i / LOG_SIZE_REG) * start_level);
break;
case KEY_PAUSE :
wait_key();
break;
case KEY_ROTATE :
show_form(5);
break;
}
}
}
}
remove_full_line();
flush_key_buffer();
choose_form();
}
if ( key != KEY_END )
{
show_topscore();
flush_key_buffer();
wait_key();
}
cls();
}
}